# 分析处理模块
import pandas as pd
import numpy as np
# 替换talib库，使用numpy和pandas实现基本功能
# import talib
import matplotlib.pyplot as plt
import seaborn as sns
import sys
sys.path.append('..')
from config import TECHNICAL_INDICATORS

class Analyzer:
    def __init__(self):
        # 技术指标配置
        self.tech_config = TECHNICAL_INDICATORS
    
    def calculate_technical_indicators(self, df):
        """计算技术指标"""
        # 确保数据按日期排序
        df = df.sort_values('trade_date')
        
        # 提取OHLCV数据
        close = df['close'].values
        high = df['high'].values
        low = df['low'].values
        open_price = df['open'].values
        volume = df['vol'].values
        
        # 计算MACD - 使用pandas实现
        macd_config = self.tech_config['MACD']
        exp1 = df['close'].ewm(span=macd_config['fast_period'], adjust=False).mean()
        exp2 = df['close'].ewm(span=macd_config['slow_period'], adjust=False).mean()
        macd = exp1 - exp2
        signal = macd.ewm(span=macd_config['signal_period'], adjust=False).mean()
        hist = macd - signal
        
        df['macd'] = macd
        df['macd_signal'] = signal
        df['macd_hist'] = hist
        
        # 计算KDJ - 使用pandas实现
        kdj_config = self.tech_config['KDJ']
        low_min = df['low'].rolling(window=kdj_config['fastk_period']).min()
        high_max = df['high'].rolling(window=kdj_config['fastk_period']).max()
        
        rsv = 100 * ((df['close'] - low_min) / (high_max - low_min))
        df['k'] = rsv.rolling(window=kdj_config['slowk_period']).mean()
        df['d'] = df['k'].rolling(window=kdj_config['slowd_period']).mean()
        df['j'] = 3 * df['k'] - 2 * df['d']
        
        # 计算RSI - 使用pandas实现
        rsi_config = self.tech_config['RSI']
        delta = df['close'].diff()
        gain = delta.where(delta > 0, 0)
        loss = -delta.where(delta < 0, 0)
        
        avg_gain = gain.rolling(window=rsi_config['period']).mean()
        avg_loss = loss.rolling(window=rsi_config['period']).mean()
        
        rs = avg_gain / avg_loss
        df['rsi'] = 100 - (100 / (1 + rs))
        
        # 计算布林带 - 使用pandas实现
        boll_config = self.tech_config['BOLL']
        df['boll_middle'] = df['close'].rolling(window=boll_config['timeperiod']).mean()
        df['boll_std'] = df['close'].rolling(window=boll_config['timeperiod']).std()
        df['boll_upper'] = df['boll_middle'] + boll_config['nbdevup'] * df['boll_std']
        df['boll_lower'] = df['boll_middle'] - boll_config['nbdevdn'] * df['boll_std']
        
        # 计算移动平均线
        df['ma5'] = df['close'].rolling(window=5).mean()
        df['ma10'] = df['close'].rolling(window=10).mean()
        df['ma20'] = df['close'].rolling(window=20).mean()
        df['ma30'] = df['close'].rolling(window=30).mean()
        
        # 计算成交量变化
        df['volume_ma5'] = df['vol'].rolling(window=5).mean()
        df['volume_change'] = df['vol'] / df['volume_ma5'] - 1
        
        return df
    
    def analyze_price_trend(self, df):
        """分析价格趋势"""
        result = {}
        
        # 获取最近的数据
        recent_data = df.iloc[-5:]
        latest_data = df.iloc[-1]
        prev_data = df.iloc[-2] if len(df) > 1 else None
        
        # 计算当日涨跌幅
        if prev_data is not None:
            result['daily_change'] = (latest_data['close'] - prev_data['close']) / prev_data['close'] * 100
        else:
            result['daily_change'] = 0
        
        # 计算5日、10日涨跌幅
        if len(df) >= 5:
            result['5day_change'] = (latest_data['close'] - df.iloc[-6]['close']) / df.iloc[-6]['close'] * 100
        else:
            result['5day_change'] = 0
            
        if len(df) >= 10:
            result['10day_change'] = (latest_data['close'] - df.iloc[-11]['close']) / df.iloc[-11]['close'] * 100
        else:
            result['10day_change'] = 0
        
        # 判断趋势
        ma5 = recent_data['ma5'].values
        ma10 = recent_data['ma10'].values
        ma20 = recent_data['ma20'].values
        
        # 短期趋势：MA5与收盘价的关系
        if latest_data['close'] > latest_data['ma5']:
            result['short_trend'] = '上涨'
        else:
            result['short_trend'] = '下跌'
        
        # 中期趋势：MA5与MA10的关系
        if latest_data['ma5'] > latest_data['ma10']:
            result['mid_trend'] = '上涨'
        else:
            result['mid_trend'] = '下跌'
        
        # 长期趋势：MA10与MA20的关系
        if latest_data['ma10'] > latest_data['ma20']:
            result['long_trend'] = '上涨'
        else:
            result['long_trend'] = '下跌'
        
        return result
    
    def analyze_volume(self, df):
        """分析成交量"""
        result = {}
        
        # 获取最近的数据
        recent_data = df.iloc[-5:]
        latest_data = df.iloc[-1]
        prev_data = df.iloc[-2] if len(df) > 1 else None
        
        # 计算成交量变化
        if prev_data is not None:
            result['volume_change'] = (latest_data['vol'] - prev_data['vol']) / prev_data['vol'] * 100
        else:
            result['volume_change'] = 0
        
        # 判断成交量趋势
        vol_ma5 = recent_data['volume_ma5'].values
        if latest_data['vol'] > latest_data['volume_ma5']:
            result['volume_trend'] = '放量'
        else:
            result['volume_trend'] = '缩量'
        
        # 判断量价关系
        if prev_data is not None:
            price_up = latest_data['close'] > prev_data['close']
            volume_up = latest_data['vol'] > prev_data['vol']
            
            if price_up and volume_up:
                result['vol_price_relation'] = '量价齐升，看多'
            elif price_up and not volume_up:
                result['vol_price_relation'] = '价升量缩，需谨慎'
            elif not price_up and volume_up:
                result['vol_price_relation'] = '价跌量增，看空'
            else:
                result['vol_price_relation'] = '价跌量缩，关注企稳'
        else:
            result['vol_price_relation'] = '数据不足'
        
        return result
    
    def analyze_technical_indicators(self, df):
        """分析技术指标"""
        result = {}
        
        # 获取最新数据
        latest_data = df.iloc[-1]
        prev_data = df.iloc[-2] if len(df) > 1 else None
        
        # MACD分析
        if prev_data is not None:
            # MACD金叉/死叉判断
            if prev_data['macd_hist'] < 0 and latest_data['macd_hist'] > 0:
                result['macd_signal'] = 'MACD金叉，买入信号'
            elif prev_data['macd_hist'] > 0 and latest_data['macd_hist'] < 0:
                result['macd_signal'] = 'MACD死叉，卖出信号'
            elif latest_data['macd_hist'] > 0 and latest_data['macd_hist'] > prev_data['macd_hist']:
                result['macd_signal'] = 'MACD柱状图增长，多头增强'
            elif latest_data['macd_hist'] < 0 and latest_data['macd_hist'] < prev_data['macd_hist']:
                result['macd_signal'] = 'MACD柱状图减小，空头增强'
            else:
                result['macd_signal'] = 'MACD无明显信号'
        else:
            result['macd_signal'] = '数据不足'
        
        # KDJ分析
        if not pd.isna(latest_data['k']) and not pd.isna(latest_data['d']):
            if latest_data['k'] > latest_data['d']:
                if latest_data['k'] < 20:
                    result['kdj_signal'] = 'KDJ金叉且处于超卖区域，强烈买入信号'
                elif latest_data['k'] > 80:
                    result['kdj_signal'] = 'KDJ金叉但处于超买区域，谨慎对待'
                else:
                    result['kdj_signal'] = 'KDJ金叉，买入信号'
            else:
                if latest_data['k'] > 80:
                    result['kdj_signal'] = 'KDJ死叉且处于超买区域，强烈卖出信号'
                elif latest_data['k'] < 20:
                    result['kdj_signal'] = 'KDJ死叉但处于超卖区域，谨慎对待'
                else:
                    result['kdj_signal'] = 'KDJ死叉，卖出信号'
        else:
            result['kdj_signal'] = '数据不足'
        
        # RSI分析
        if not pd.isna(latest_data['rsi']):
            if latest_data['rsi'] > 70:
                result['rsi_signal'] = 'RSI大于70，超买区域，考虑卖出'
            elif latest_data['rsi'] < 30:
                result['rsi_signal'] = 'RSI小于30，超卖区域，考虑买入'
            else:
                result['rsi_signal'] = 'RSI在中性区域，无明显信号'
        else:
            result['rsi_signal'] = '数据不足'
        
        # 布林带分析
        if not pd.isna(latest_data['boll_upper']) and not pd.isna(latest_data['boll_lower']):
            if latest_data['close'] > latest_data['boll_upper']:
                result['boll_signal'] = '价格突破布林上轨，超买状态，可能回调'
            elif latest_data['close'] < latest_data['boll_lower']:
                result['boll_signal'] = '价格跌破布林下轨，超卖状态，可能反弹'
            else:
                width = (latest_data['boll_upper'] - latest_data['boll_lower']) / latest_data['boll_middle']
                if width < 0.1:
                    result['boll_signal'] = '布林带收窄，可能即将突破'
                else:
                    result['boll_signal'] = '价格在布林带内运行，无明显信号'
        else:
            result['boll_signal'] = '数据不足'
        
        return result
    
    def compare_with_market(self, stock_df, index_df):
        """与大盘表现对比"""
        result = {}
        
        # 确保两个DataFrame都有数据
        if stock_df.empty or index_df.empty:
            return {'comparison': '数据不足，无法比较'}
        
        # 获取相同的日期范围
        common_dates = set(stock_df['trade_date']).intersection(set(index_df['trade_date']))
        if not common_dates:
            return {'comparison': '没有共同的交易日期，无法比较'}
        
        # 筛选共同日期的数据
        stock_filtered = stock_df[stock_df['trade_date'].isin(common_dates)].sort_values('trade_date')
        index_filtered = index_df[index_df['trade_date'].isin(common_dates)].sort_values('trade_date')
        
        # 计算最近一日涨跌幅
        latest_stock = stock_filtered.iloc[-1]
        prev_stock = stock_filtered.iloc[-2] if len(stock_filtered) > 1 else None
        
        latest_index = index_filtered.iloc[-1]
        prev_index = index_filtered.iloc[-2] if len(index_filtered) > 1 else None
        
        if prev_stock is not None and prev_index is not None:
            stock_change = (latest_stock['close'] - prev_stock['close']) / prev_stock['close'] * 100
            index_change = (latest_index['close'] - prev_index['close']) / prev_index['close'] * 100
            
            result['stock_change'] = stock_change
            result['index_change'] = index_change
            result['diff'] = stock_change - index_change
            
            if stock_change > index_change:
                result['comparison'] = f'股票表现强于大盘 {abs(result["diff"]):.2f}%'
            elif stock_change < index_change:
                result['comparison'] = f'股票表现弱于大盘 {abs(result["diff"]):.2f}%'
            else:
                result['comparison'] = '股票表现与大盘持平'
        else:
            result['comparison'] = '数据不足，无法比较'
        
        # 计算5日、10日相对强弱
        if len(stock_filtered) >= 5 and len(index_filtered) >= 5:
            stock_5d_change = (latest_stock['close'] - stock_filtered.iloc[-6]['close']) / stock_filtered.iloc[-6]['close'] * 100
            index_5d_change = (latest_index['close'] - index_filtered.iloc[-6]['close']) / index_filtered.iloc[-6]['close'] * 100
            
            result['stock_5d_change'] = stock_5d_change
            result['index_5d_change'] = index_5d_change
            result['5d_diff'] = stock_5d_change - index_5d_change
            
            if stock_5d_change > index_5d_change:
                result['5d_comparison'] = f'5日内股票表现强于大盘 {abs(result["5d_diff"]):.2f}%'
            elif stock_5d_change < index_5d_change:
                result['5d_comparison'] = f'5日内股票表现弱于大盘 {abs(result["5d_diff"]):.2f}%'
            else:
                result['5d_comparison'] = '5日内股票表现与大盘持平'
        
        # 计算10日相对强弱
        if len(stock_filtered) >= 10 and len(index_filtered) >= 10:
            stock_10d_change = (latest_stock['close'] - stock_filtered.iloc[-11]['close']) / stock_filtered.iloc[-11]['close'] * 100
            index_10d_change = (latest_index['close'] - index_filtered.iloc[-11]['close']) / index_filtered.iloc[-11]['close'] * 100
            
            result['stock_10d_change'] = stock_10d_change
            result['index_10d_change'] = index_10d_change
            result['10d_diff'] = stock_10d_change - index_10d_change
            
            if stock_10d_change > index_10d_change:
                result['10d_comparison'] = f'10日内股票表现强于大盘 {abs(result["10d_diff"]):.2f}%'
            elif stock_10d_change < index_10d_change:
                result['10d_comparison'] = f'10日内股票表现弱于大盘 {abs(result["10d_diff"]):.2f}%'
            else:
                result['10d_comparison'] = '10日内股票表现与大盘持平'
        
        return result
    
    def analyze_money_flow(self, money_flow_df):
        """分析资金流向"""
        result = {}
        
        if money_flow_df.empty:
            return {'money_flow': '数据不足，无法分析'}
        
        # 获取最近的数据
        latest_data = money_flow_df.iloc[-1]
        
        # 计算主力资金净流入
        result['net_mf_amount'] = latest_data['net_mf_amount'] if 'net_mf_amount' in latest_data else 0
        
        # 计算大单资金流向
        result['buy_lg_amount'] = latest_data['buy_lg_amount'] if 'buy_lg_amount' in latest_data else 0
        result['sell_lg_amount'] = latest_data['sell_lg_amount'] if 'sell_lg_amount' in latest_data else 0
        result['net_lg_amount'] = latest_data['net_lg_amount'] if 'net_lg_amount' in latest_data else 0
        
        # 计算中单资金流向
        result['buy_md_amount'] = latest_data['buy_md_amount'] if 'buy_md_amount' in latest_data else 0
        result['sell_md_amount'] = latest_data['sell_md_amount'] if 'sell_md_amount' in latest_data else 0
        result['net_md_amount'] = latest_data['net_md_amount'] if 'net_md_amount' in latest_data else 0
        
        # 计算小单资金流向
        result['buy_sm_amount'] = latest_data['buy_sm_amount'] if 'buy_sm_amount' in latest_data else 0
        result['sell_sm_amount'] = latest_data['sell_sm_amount'] if 'sell_sm_amount' in latest_data else 0
        result['net_sm_amount'] = latest_data['net_sm_amount'] if 'net_sm_amount' in latest_data else 0
        
        # 判断资金流向
        if result['net_mf_amount'] > 0:
            result['money_flow'] = '资金净流入，看多'
        else:
            result['money_flow'] = '资金净流出，看空'
        
        # 判断大单与小单的关系
        if result['net_lg_amount'] > 0 and result['net_sm_amount'] < 0:
            result['lg_sm_relation'] = '大单买入，小单卖出，主力进场'
        elif result['net_lg_amount'] < 0 and result['net_sm_amount'] > 0:
            result['lg_sm_relation'] = '大单卖出，小单买入，主力出货'
        elif result['net_lg_amount'] > 0 and result['net_sm_amount'] > 0:
            result['lg_sm_relation'] = '大单小单均买入，市场看多'
        else:
            result['lg_sm_relation'] = '大单小单均卖出，市场看空'
        
        return result